/**
 * DSM - Distributed Search Manager
 * Developed by Milspec Research International Pty Ltd
 * $Author: gsingh $
 * $Revision: 1.3 $
 * $Date: 2006/02/28 06:08:16 $
 * (c)Copyright 2004
 * education.au limited
 * DEST
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 * Neither the names education.au limited, DEST nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 * To the extent permitted by law, the copyright owners of this software and
 * its contributors:
 * (i) exclude all warranties in relation to the software; and
 * (ii) exclude liability for all losses, costs, expenses and damages arising
 * in any way from the use of the software whether arising from or in
 * relation to breach of contract, negligence or any other tort, in equity
 * or otherwise. If the software is in breach of a warranty which is
 * implied by law, the copyright owners and contributors liability is
 * limited to the replacement of the software.
 *
 * @author	gsingh
 */

package au.edu.educationau.opensource.dsm.adapters;

import java.io.BufferedReader;
import java.io.StringReader;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Enumeration;

import au.edu.educationau.opensource.dsm.DeusExMachina;
import au.edu.educationau.opensource.dsm.adapters.contenthandler.SRWContentHandler;
import au.edu.educationau.opensource.dsm.obj.SearchCriteria;
import au.edu.educationau.opensource.dsm.util.EducationAuUtils;
import au.edu.educationau.opensource.dsm.worker.ResultSetUnifier;

/**
 * SRW Soap Adapter using Stubs
 */

public class SRWSearchAdapterImpl extends SearchAdapter {
	private int found = 0;
	private StringBuffer soapBody = new StringBuffer();
	private String uniqueIdentifier = "";

	/** Parent constructor */
	public SRWSearchAdapterImpl() {
		super();
	}

	/**
	 * See the SearchAdapter abstract method doPrime
	 * 
	 * @exception Throwable
	 * 
	 * @example
	 * 
	 * &lt;SRW:searchRetrieveRequest
	 * xmlns:SRW="http://www.loc.gov/zing/srw/v1.0/"&gt;
	 * &lt;SRW:version&gt;1.1&lt;/SRW:version&gt;
	 * &lt;SRW:query&gt;frogs&lt;/SRW:query&gt;
	 * &lt;SRW:startRecord&gt;1&lt;/SRW:startRecord&gt;
	 * &lt;SRW:maximumRecords&gt;10&lt;/SRW:maximumRecords&gt;
	 * &lt;SRW:recordSchema&gt;dc&lt;/SRW:recordSchema&gt;
	 * &lt;SRW:extraRequestData
	 * xmlns:dsm="http://www.edna.edu.au/schema/edna_dsm_v1p0/"&gt;
	 * &lt;dsm:sr&gt;edna&lt;/dsm:sr&gt; &lt;dsm:sr&gt;abcall&lt;/dsm:sr&gt;
	 * &lt;dsm:ss&gt;waitfast&lt;/dsm:ss&gt;
	 * &lt;dsm:user&gt;tester1234&lt;/dsm:user&gt; &lt;/SRW:extraRequestData&gt;
	 * &lt;/SRW:searchRetrieveRequest&gt;
	 */
	public void doPrime() throws Throwable {
		// Build the SRW Soap Request here
		SearchCriteria criteria = super.getSearchCriteria();
		soapBody.append("<SRW:searchRetrieveRequest xmlns:SRW=\"http://www.loc.gov/zing/srw/\">").append("<SRW:version>").append(super.getProperties().getExtraProperty("version")).append("</SRW:version>").append("<SRW:query>");
		if (criteria.getCQLQuery() != null && criteria.getCQLQuery().length() > 0) {
			soapBody.append(criteria.getCQLQuery());
		} else {
			soapBody.append(URLEncoder.encode(criteria.getQuery(), "UTF-8"));
		}
		soapBody.append("</SRW:query>").append("<SRW:startRecord>").append("1").append("</SRW:startRecord>").append("<SRW:maximumRecords>").append(super.getProperties().getBatchSize()).append("</SRW:maximumRecords>");
		if (null != super.getProperties().getExtraProperty("recordSchema")) {
			soapBody.append("<SRW:recordSchema>").append(super.getProperties().getExtraProperty("recordSchema")).append("</SRW:recordSchema>");
		}
		if (null != super.getProperties().getExtraProperty("recordPacking")) {
			soapBody.append("<SRW:recordPacking>").append(super.getProperties().getExtraProperty("recordPacking")).append("</SRW:recordPacking>");
		}
		if (null != super.getProperties().getExtraProperty("recordXPath")) {
			soapBody.append("<SRW:recordXPath>").append(super.getProperties().getExtraProperty("recordXPath")).append("</SRW:recordXPath>");
		}
		if (null != super.getProperties().getExtraProperty("resultSetTTL")) {
			soapBody.append("<SRW:resultSetTTL>").append(super.getProperties().getExtraProperty("resultSetTTL")).append("</SRW:resultSetTTL>");
		}
		if (null != super.getProperties().getExtraProperty("sortKeys")) {
			soapBody.append("<SRW:sortKeys>").append(super.getProperties().getExtraProperty("sortKeys")).append("</SRW:sortKeys>");
		}
		if (null != super.getProperties().getExtraProperty("stylesheet")) {
			soapBody.append("<SRW:stylesheet>").append(super.getProperties().getExtraProperty("stylesheet")).append("</SRW:stylesheet>");
		}

		soapBody.append("<SRW:extraRequestData xmlns:dsm=\"http://www.edna.edu.au/schema/edna_dsm_v1p0/\">");

		if (null != super.getProperties().getExtraProperty("authenticateuser") && super.getProperties().getExtraProperty("authenticateuser").equals("true")) {
			if (null != super.getProperties().getExtraProperty("x-user")) {
				soapBody.append("<dsm:user>").append(super.getProperties().getExtraProperty("x-user")).append("</dsm:user>");
			} else {
				soapBody.append("<dsm:user>").append(criteria.getUserCode()).append("</dsm:user>");
			}
		}

		if (criteria.hasCustomParams()) {
			String param = "";
			String adapterName = super.getProperties().getAdapterCode() + ".";
			for (Enumeration params = criteria.getCustomParams(); params.hasMoreElements();) {
				param = (String) params.nextElement();
				if (param.startsWith(adapterName) && param.length() > adapterName.length()) {
					String[] paramVals = criteria.getCustomParamValues(param);

					if (null != paramVals) {
						for (int i = 0; i < paramVals.length; i++) {
							soapBody.append("<dsm:qp name=\"").append(param.substring(adapterName.length())).append("\">").append(paramVals[i]).append("</dsm:qp>");
						}
					}
				}
			}
		}

		soapBody.append("</SRW:extraRequestData>").append("</SRW:searchRetrieveRequest>");

		uniqueIdentifier = soapBody.toString();
	}

	/**
	 * See the SearchAdapter abstract method doPerform
	 * 
	 * @exception Throwable
	 */
	public ArrayList doPerform() throws Throwable {
		StringReader reader;

		if (DeusExMachina._SOAPSearchResultCacheService().hasResults(super.getProperties().getAdapterCode(), uniqueIdentifier)) {
			reader = new StringReader((String) DeusExMachina._SOAPSearchResultCacheService().getResults(super.getProperties().getAdapterCode(), uniqueIdentifier));
		} else {
			String data = EducationAuUtils.SOAPTransation(soapBody.toString(), new URL(super.getAugmentedSearchURL()), super.getAugmentedSearchURL());
			DeusExMachina._SOAPSearchResultCacheService().addResults(super.getProperties().getAdapterCode(), uniqueIdentifier, data);
			reader = new StringReader(data);
		}

		SRWContentHandler cHandler = new SRWContentHandler();
		cHandler.setSearchAdapterProperties(super.getProperties());
		cHandler.setSearchCriteria(super.getSearchCriteria());
		cHandler = (SRWContentHandler) ResultSetUnifier.processXML(new BufferedReader(reader), cHandler);
		super.setDiagnosticCode(cHandler.getDiagnosticCode());
		return cHandler.getResults();
	}

	/**
	 * See the SearchAdapter abstract method doNextBatch
	 * 
	 * @exception Throwable
	 */
	public boolean doNextBatch() throws Throwable {
		return false;
	}

	/**
	 * See the SearchAdapter abstract method doStopNice
	 * 
	 * @exception Throwable
	 */
	public void doStopNice() throws Throwable {
		// does nothing here
	}

	/**
	 * See the SearchAdapter abstract method doStopForce
	 * 
	 * @exception Throwable
	 */
	public void doStopForce() throws Throwable {
		// does nothing here
	}

	/** Class name display */
	public String toString() {
		return "o.m.d.a.SRWSearchAdapterImpl";
	}
} // -- EOF
